package com.gec.controllers;

import java.util.*;
import java.math.*;

import cn.hutool.core.util.StrUtil;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.node.ObjectNode;

import com.gec.pagination.PagedResult;
import io.quarkus.hibernate.orm.panache.PanacheQuery;
import io.quarkus.panache.common.Page;
import io.quarkus.panache.common.Sort;
import jakarta.annotation.security.RolesAllowed;
import jakarta.enterprise.context.ApplicationScoped;
import jakarta.inject.Inject;
import jakarta.persistence.EntityManager;
import jakarta.transaction.Transactional;
import jakarta.ws.rs.*;
import jakarta.ws.rs.core.MediaType;
import jakarta.ws.rs.core.Response;
import jakarta.ws.rs.ext.ExceptionMapper;
import jakarta.ws.rs.ext.Provider;

import com.gec.entities.School;
import org.jboss.logging.Logger;

import java.util.*;

import static com.gec.Generics.GenericHelper.updateEntity;

@Path("school")
@ApplicationScoped
@Produces(MediaType.APPLICATION_JSON)
@Consumes(MediaType.APPLICATION_JSON)
@RolesAllowed({"VIEW_ADMIN_DETAILS"})
public class SchoolController {

    @Inject
    EntityManager entityManager;

    private static final Logger LOGGER = Logger.getLogger(SchoolController.class.getName());

    /**
     * 列出所有学校信息。
     *
     * @param page        页码，从0开始。
     * @param size        每页大小。
     * @param sort        排序字段。
     * @param schoolName  学校名称过滤条件。
     * @param address     地址过滤条件。
     * @param phoneNumber 电话号码过滤条件。
     * @return 包含学校列表的响应对象。
     */
    @GET
    public Response listAll(
            @QueryParam("page") Integer page,
            @QueryParam("size") Integer size,
            @QueryParam("sort") String sort,
            @QueryParam("schoolName") String schoolName,
            @QueryParam("address") String address,
            @QueryParam("phoneNumber") String phoneNumber
    ) {
        // 初始化分页和排序参数
        size = (size == null) ? 10 : size;
        page = (page == null) ? 0 : page;
        sort = (Objects.equals(sort, "")) ? "schoolName" : sort;

        String validSortColumn = "schoolName";
        List<String> validSortColumns = Arrays.asList("schoolName", "address", "phoneNumber");
        if (validSortColumns.contains(sort)) {
            validSortColumn = sort;
        }

        // 构建查询字符串和参数
        String queryStr = "FROM School WHERE 1=1";
        Map<String, Object> params = new HashMap<>();

        if (StrUtil.isNotBlank(schoolName)) {
            queryStr += " AND LOWER(schoolName) LIKE LOWER(CONCAT('%', :schoolName, '%'))";
            params.put("schoolName", schoolName);
        }
        if (StrUtil.isNotBlank(address)) {
            queryStr += " AND LOWER(address) LIKE LOWER(CONCAT('%', :address, '%'))";
            params.put("address", address);
        }
        if (StrUtil.isNotBlank(phoneNumber)) {
            queryStr += " AND LOWER(phoneNumber) LIKE LOWER(CONCAT('%', :phoneNumber, '%'))";
            params.put("phoneNumber", phoneNumber);
        }

        // 执行查询
        PanacheQuery<School> query = School.find(queryStr, Sort.by(validSortColumn), params);
        Long totalCount = query.count();
        List<School> schools = query.page(Page.of(page, size)).list();

        // 构建并返回分页结果
        return Response.ok(
                new PagedResult<>(
                        schools,
                        totalCount,
                        (int) Math.ceil((double) totalCount / size),
                        page > 0,
                        (page + 1) * size < totalCount
                )
        ).build();
    }

    /**
     * 更新指定 ID 的学校信息。
     *
     * @param id          学校 ID。
     * @param updatedSchool 包含更新信息的学校对象。
     * @return 响应对象，包含更新后的学校信息。
     */
    @PUT
    @Path("{id}")
    @Transactional
    public Response updateSchool(@PathParam("id") Long id, School updatedSchool) {
        School school = School.findById(id);
        if (school == null) {
            return Response.status(Response.Status.NOT_FOUND).build();
        }
        updateEntity(school, updatedSchool);
        return Response.ok(school).build();
    }

    /**
     * 创建新的学校信息。
     *
     * @param entity 新学校对象。
     * @return 响应对象，表示创建结果。
     */
    @POST
    @Transactional
    public Response create(School entity) {
        if (entity.id != null) {
            throw new WebApplicationException("Id was invalidly set on request.", 422);
        }

        entity.persist();
        return Response.ok(entity).status(201).build();
    }

    /**
     * 删除指定 ID 的学校信息。
     *
     * @param id 学校 ID。
     * @return 表示删除结果的响应对象。
     */
    @DELETE
    @Path("{id}")
    @Transactional
    public Response delete(Long id) {
        School entity = School.findById(id);
        if (entity == null) {
            throw new WebApplicationException("School with id of " + id + " does not exist.", 404);
        }
        entity.delete();
        return Response.status(204).build();
    }

    /**
     * 全局异常处理映射器，将异常转换为标准化的响应。
     */
    @Provider
    public static class ErrorMapper implements ExceptionMapper<Exception> {

        @Inject
        ObjectMapper objectMapper;

        @Override
        public Response toResponse(Exception exception) {
            LOGGER.error("Failed to handle request", exception);

            int code = 500;
            if (exception instanceof WebApplicationException) {
                code = ((WebApplicationException) exception).getResponse().getStatus();
            }

            ObjectNode exceptionJson = objectMapper.createObjectNode();
            exceptionJson.put("exceptionType", exception.getClass().getName());
            exceptionJson.put("code", code);

            if (exception.getMessage() != null) {
                exceptionJson.put("error", exception.getMessage());
            }

            return Response.status(code)
                    .entity(exceptionJson)
                    .build();
        }

    }
}
